package com.navinfo.routeplan

import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.provider.Settings
import android.util.Log
import android.view.View
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.ViewModelProvider
import com.github.lazylibrary.util.RandomUtils
import com.github.lazylibrary.util.RegularExpression
import com.haoge.easyandroid.easy.EasySharedPreferences
import com.haoge.easyandroid.easy.EasyToast
import com.kongzue.dialogx.dialogs.CustomDialog
import com.kongzue.dialogx.dialogs.InputDialog
import com.kongzue.dialogx.dialogs.MessageDialog
import com.kongzue.dialogx.interfaces.OnBindView
import com.kongzue.dialogx.interfaces.OnInputDialogButtonClickListener
import com.navinfo.routeplan.databinding.ActivityMainBinding
import com.navinfo.routeplan.databinding.DialogSettingBinding
import com.navinfo.routeplan.databinding.DialogTimeRangeSelectBinding
import com.navinfo.routeplan.entity.GetNaviDataResponse
import com.navinfo.routeplan.entity.NaviData
import com.navinfo.routeplan.entity.PostNaviDataRequest
import com.navinfo.routeplan.entity.PostNaviDataResponse
import com.navinfo.routeplan.entity.RouteData
import com.navinfo.routeplan.request.IcroadRequestService
import com.navinfo.routeplan.viewmodel.MainActivityViewModel
import com.tencent.lbssearch.TencentSearch
import com.tencent.lbssearch.httpresponse.HttpResponseListener
import com.tencent.lbssearch.`object`.param.DrivingParam
import com.tencent.lbssearch.`object`.result.DrivingResultObject
import com.tencent.tencentmap.mapsdk.maps.TencentMapInitializer
import com.tencent.tencentmap.mapsdk.maps.model.LatLng
import com.teprinciple.mailsender.Mail
import com.teprinciple.mailsender.MailSender
import com.teprinciple.mailsender.MailSender.getInstance
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import java.text.SimpleDateFormat
import java.time.LocalTime
import java.util.Date
import kotlin.random.Random


class MainActivity : AppCompatActivity() {
    private val currentViewModel by lazy { ViewModelProvider(this@MainActivity).get(MainActivityViewModel::class.java) }
    private val activityMainBinding by lazy { ActivityMainBinding.inflate(layoutInflater) }
    private val tencentSearch by lazy {TencentSearch(applicationContext)}
    private val requeestService by lazy { Constant.retrofit.create(IcroadRequestService::class.java) }
    private val simpleDateFormat: SimpleDateFormat by lazy { SimpleDateFormat("yyyy-MM-dd HH:mm:ss") }
    private val simpleTimeFormat: SimpleDateFormat by lazy { SimpleDateFormat("HH:mm") }
    private var getNaviDataRetryCount = 0
    private var getRouteRetryCount = 0
    private var postNaviDataRetryCount = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        /**
         * 设置用户是否同意隐私协议
         * 需要在初始化地图之前完成，传入true后才能正常使用地图功能
         * @param isAgree 是否同意隐私协议
         */
        TencentMapInitializer.setAgreePrivacy(true);

        setContentView(activityMainBinding.root)
        ViewCompat.setOnApplyWindowInsetsListener(activityMainBinding.main) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }

        // 判断当前应用是否有唯一标识
        val deviceId = EasySharedPreferences.getSPValue(Constant.SP_DEVICE_ID, "")
        if (deviceId.isEmpty()) {
            // 获取当前deviceId
            val currentDeviceId = Settings.System.getString(applicationContext.contentResolver, Settings.Secure.ANDROID_ID)
            // 显示对话框，要求用户输入设备昵称
            InputDialog.build().setInputHintText("请输入设备别名alias")
                .setTitle("设置设备别名")
                .setInputText(currentDeviceId).setCancelable(false).setOkButton("确定", object :
                OnInputDialogButtonClickListener<InputDialog> {
                override fun onClick(dialog: InputDialog?, v: View?, inputStr: String?): Boolean {
                    if (inputStr?.isNullOrEmpty() == true) {
                        EasySharedPreferences.putSPValue(Constant.SP_DEVICE_ID, currentDeviceId)
                    } else {
                        EasySharedPreferences.putSPValue(Constant.SP_DEVICE_ID, inputStr)
                    }
                    return false
                }
            }).show()
        }

        initView()
    }

    private fun initView() {
        // 设置右上角开始按钮
        activityMainBinding.tvStartCaculate.setOnClickListener {
            // 设置选中状态
            it.isSelected = !it.isSelected
            if (it.isSelected) {
                activityMainBinding.tvStartCaculate.text = "停止"

                handler.sendEmptyMessage(Constant.MSG_WHAT_GET_NAVI_DATA)
            } else { // 停止
                activityMainBinding.tvStartCaculate.text = "开始"
            }
        }
        // 点击设置按钮
        activityMainBinding.btnSetting.setOnClickListener {
            val dialogSettingBinding = DialogSettingBinding.inflate(layoutInflater)
            CustomDialog.build()
                .setCustomView(object : OnBindView<CustomDialog>(dialogSettingBinding.root) {
                    override fun onBind(dialog: CustomDialog?, v: View?) {
                        // 获取setting保存的数据
                        val baseUrl = EasySharedPreferences.getSPValue(Constant.SP_BASE_URL, Constant.REQUEST_BASE_URL)
                        val onceCount: Int = EasySharedPreferences.getSPValue(Constant.SP_ONCE_COUNT, Constant.DEFAULT_ONCE_COUNT)
                        val interval: Int = EasySharedPreferences.getSPValue(Constant.SP_INTERVAL, Constant.DEFAULT_INTERVAL)
                        val retryInterval: Int = EasySharedPreferences.getSPValue(Constant.SP_RETRY_INTERVAL, Constant.DEFAULT_RETRY_INTERVAL)
                        val email: String = EasySharedPreferences.getSPValue(Constant.SP_EMAIL, Constant.DEFAULT_EMAIL)
                        val routeErrorSendEmail: Boolean = EasySharedPreferences.getSPValue(Constant.SP_ROUTE_ERROR_SEND_MAIL, Constant.DEFAULT_ROUTE_ERROR_SEND_MAIL)
                        val workTime: String = EasySharedPreferences.getSPValue(Constant.SP_WORK_TIME, Constant.DEFAULT_WORK_TIME)
                        dialogSettingBinding.edtSettingBaseUrl.setText(baseUrl)
                        dialogSettingBinding.edtSettingOnceCount.setText(onceCount.toString())
                        dialogSettingBinding.edtSettingInterval.setText(interval.toString())
                        dialogSettingBinding.edtSettingRetryInterval.setText(retryInterval.toString())
                        dialogSettingBinding.edtSettingEmail.setText(email)
                        dialogSettingBinding.chkSettingRouteError.isChecked = routeErrorSendEmail
                        dialogSettingBinding.tvSettingWorkTime.text = workTime

                        // 工作时间点击事件处理
                        dialogSettingBinding.tvSettingWorkTime.setOnClickListener {
                            val dialogTimeRangeBinding = DialogTimeRangeSelectBinding.inflate(layoutInflater)
                            CustomDialog.build()
                                .setCustomView(object : OnBindView<CustomDialog>(dialogTimeRangeBinding.root) {
                                    override fun onBind(dialog: CustomDialog?, v: View?) {
                                        dialogTimeRangeBinding.btnTimerangeCancel.setOnClickListener {
                                            dialog!!.dismiss()
                                        }
                                        dialogTimeRangeBinding.btnTimerangeOk.setOnClickListener {
                                            dialogSettingBinding.tvSettingWorkTime.text = "${dialogTimeRangeBinding.picker.startTime.localTime}-${dialogTimeRangeBinding.picker.endTime.localTime}"
                                            dialog!!.dismiss()
                                        }
                                    }

                                })
                                .setAlign(CustomDialog.ALIGN.CENTER)
                                .setCancelable(false)
                                .show(this@MainActivity)
                        }

                        // 保存setting数据
                        dialogSettingBinding.btnSettingOk.setOnClickListener {
                            val baseUrl = dialogSettingBinding.edtSettingBaseUrl.text.toString()
                            val onceCount = dialogSettingBinding.edtSettingOnceCount.text.toString().toInt()
                            val interval = dialogSettingBinding.edtSettingInterval.text.toString().toInt()
                            val retryInterval = dialogSettingBinding.edtSettingRetryInterval.text.toString().toInt()
                            val email = dialogSettingBinding.edtSettingEmail.text.toString()
                            val routeErrorSendEmail = dialogSettingBinding.chkSettingRouteError.isChecked
                            // 判断email设置是否有效
                            if (email.isNullOrEmpty()) {
                                EasyToast.DEFAULT.show("错误信息收件箱地址不能为空");
                                return@setOnClickListener
                            }
                            if (!RegularExpression.isEmail(email)) {
                                EasyToast.DEFAULT.show("错误信息收件箱地址格式错误");
                                return@setOnClickListener
                            }

                            EasySharedPreferences.putSPValue(Constant.SP_BASE_URL, baseUrl)
                            EasySharedPreferences.putSPValue(Constant.SP_ONCE_COUNT, onceCount)
                            EasySharedPreferences.putSPValue(Constant.SP_INTERVAL, interval)
                            EasySharedPreferences.putSPValue(Constant.SP_RETRY_INTERVAL, retryInterval)
                            EasySharedPreferences.putSPValue(Constant.SP_EMAIL, email)
                            EasySharedPreferences.putSPValue(Constant.SP_ROUTE_ERROR_SEND_MAIL, routeErrorSendEmail)
                            EasySharedPreferences.putSPValue(Constant.SP_WORK_TIME, dialogSettingBinding.tvSettingWorkTime.text.toString())
                            dialog?.dismiss()
                        }
                        dialogSettingBinding.btnSettingCancel.setOnClickListener {
                            dialog?.dismiss()
                        }
                    }
                })
                .setAlign(CustomDialog.ALIGN.CENTER)
                .setCancelable(false)
                .show(this@MainActivity)
        }
    }

    fun startCaculate() {
        // 获取当前时间
        val currtentTime = LocalTime.now()
        val workTime = EasySharedPreferences.getSPValue(Constant.SP_WORK_TIME, Constant.DEFAULT_WORK_TIME)
        val startTime = LocalTime.parse(workTime.split("-")[0])
        val endTime = LocalTime.parse(workTime.split("-")[1])
        if (isTimeWithinRange(currtentTime, startTime, endTime)) {
            if (activityMainBinding.tvStartCaculate.isSelected) {
                // 开始
                requeestService.getNavData().enqueue(
                    object : Callback<GetNaviDataResponse> {
                        override fun onResponse(
                            p0: Call<GetNaviDataResponse>,
                            p1: Response<GetNaviDataResponse>
                        ) {
                            if (p1.body()?.code == 200) {
                                getNaviDataRetryCount = 0 // 重置重试次数
                                val dataList = p1.body()?.data_list
                                if (!dataList.isNullOrEmpty()) {
                                    activityMainBinding.tvMainTaskName.text = p1.body()?.task_id.toString()
                                    activityMainBinding.pbiRoute.max = dataList.size
                                    activityMainBinding.pbiRoute.progress = 0
                                    activityMainBinding.tvMainTaskDownTime.text = simpleDateFormat.format(Date())
                                    getRouteLineData(p1.body()?.task_id!!, dataList, 0, mutableListOf())
                                } else { // 获取的数据为空，等待10分钟后再次尝试获取数据
                                    activityMainBinding.tvMainTaskName.text = "任务名称"
                                    val retryInterval = EasySharedPreferences.getSPValue(Constant.SP_RETRY_INTERVAL, Constant.DEFAULT_RETRY_INTERVAL)
                                    handler.sendEmptyMessageDelayed(Constant.MSG_WHAT_GET_NAVI_DATA, retryInterval.toLong() * 1000)
                                    activityMainBinding.tvMainErrorInfo.text = "在${simpleTimeFormat.format(
                                        Date()
                                    )}获取数据为空，等待${retryInterval}秒后再次尝试获取数据"
                                }
                            }
                        }

                        override fun onFailure(p0: Call<GetNaviDataResponse>, p1: Throwable) {
                            // 请求数据出错，将错误信息显示在界面上
                            if (++getNaviDataRetryCount<3) {
                                activityMainBinding.tvMainErrorInfo.text = "请求数据失败：${p1.message} \r\n尝试第${getNaviDataRetryCount}次获取数据"
                                handler.sendEmptyMessage(Constant.MSG_WHAT_GET_NAVI_DATA)
                            } else {
                                val retryInterval = EasySharedPreferences.getSPValue(Constant.SP_RETRY_INTERVAL, Constant.DEFAULT_RETRY_INTERVAL)
                                handler.sendEmptyMessageDelayed(Constant.MSG_WHAT_GET_NAVI_DATA, retryInterval.toLong() * 1000)
                                activityMainBinding.tvMainErrorInfo.text = "在${simpleTimeFormat.format(Date())}获取数据失败，等待${retryInterval}秒后再次尝试获取数据"
                            }
                        }

                    }
                )
            }
        } else {
            val retryInterval = EasySharedPreferences.getSPValue(Constant.SP_RETRY_INTERVAL, Constant.DEFAULT_RETRY_INTERVAL)
            activityMainBinding.tvMainErrorInfo.text = "设置的工作时间为${workTime},当前时间为${currtentTime}，${retryInterval}秒后重试"
            handler.sendEmptyMessageDelayed(Constant.MSG_WHAT_GET_NAVI_DATA, retryInterval.toLong() * 1000) // 10分钟后重试
        }
    }

    private fun getRouteLineData(taskId: String, dataList: ArrayList<NaviData>, index: Int, routeDataList: MutableList<RouteData>) {
        // 获取路径规划需要的起终点和途经点
        if (dataList[index].coordinate.size >= 4) {
            val start = LatLng(dataList[index].coordinate[1], dataList[index].coordinate[0])
            val end = LatLng(dataList[index].coordinate[dataList[index].coordinate.size-1], dataList[index].coordinate[dataList[index].coordinate.size-2])
            // 开始请求路径规划内容
            val drivingParam: DrivingParam = DrivingParam(start, end)
            for (i in 2 until dataList[index].coordinate.size - 2 step 2) {
                drivingParam.addWayPoint(LatLng(dataList[index].coordinate[i+1], dataList[index].coordinate[i]))
            }
            tencentSearch.getRoutePlan(drivingParam, object :HttpResponseListener<DrivingResultObject> {
                override fun onSuccess(p0: Int, p1: DrivingResultObject?) {
                    Log.d("MainActivity", p1?.result?.toJson().toString())
                    // 将polyline数组转换为wkt
                    val routePolyLine = GeometryTools.getLineString(p1?.result?.routes?.get(0)?.polyline)
                    if (routePolyLine!=null) {
                        // 记录路径规划数据
                        routeDataList.add(RouteData(dataList[index].id, "规划成功", EasySharedPreferences.getSPValue(Constant.SP_DEVICE_ID, ""), routePolyLine))
                        getNextRouteOrUploadData(taskId, dataList, index, routeDataList)
                    } else {
                        routeDataList.add(RouteData(dataList[index].id, "规划失败: 规划的路径为无法组成线", EasySharedPreferences.getSPValue(Constant.SP_DEVICE_ID, ""), ""))
                        getNextRouteOrUploadData(taskId, dataList, index, routeDataList)
                        sendEmail("规划路径失败", "规划的路径为无法组成线，taskId: ${taskId}, routeId: ${dataList[index].id}")
                    }
                }

                override fun onFailure(p0: Int, p1: String?, p2: Throwable?) {
                    print(p1)
                    routeDataList.add(RouteData(dataList[index].id, "规划失败: ${p1}", EasySharedPreferences.getSPValue(Constant.SP_DEVICE_ID, ""), ""))
                    getNextRouteOrUploadData(taskId, dataList, index, routeDataList)
                    if (EasySharedPreferences.getSPValue(Constant.SP_ROUTE_ERROR_SEND_MAIL, Constant.DEFAULT_ROUTE_ERROR_SEND_MAIL)) {
                        sendEmail("规划路径失败", "规划的路径失败，taskId: ${taskId}, routeId: ${dataList[index].id}，路径规划SDK返回错误信息: ${p1}")
                    }
                    // 设置不再继续处理后续任务，弹框提示用户
                    MessageDialog.build().setTitle("提示")
                        .setMessage("规划的路径失败，taskId: ${taskId}, routeId: ${dataList[index].id}，路径规划SDK返回错误信息: ${p1}, 请检查后重新开启程序？")
                        .show()
                    activityMainBinding.tvStartCaculate.isSelected = false
                }
            })
        }
    }

    fun getNextRouteOrUploadData(taskId: String, dataList: ArrayList<NaviData>, index: Int, routeDataList: MutableList<RouteData>) {
        activityMainBinding.pbiRoute.progress = index + 1
        if (index < dataList.size - 1) {// 后面还有，继续对下一个路径做请求
            val sleepTime = EasySharedPreferences.getSPValue(Constant.SP_INTERVAL, Constant.DEFAULT_INTERVAL)
            Thread.sleep(RandomUtils.getRandom(sleepTime-50, sleepTime+50).toLong()) // 随机等待指定时间
            getRouteLineData(taskId, dataList, index + 1, routeDataList)
        } else {
            // 上报数据
            requeestService.postNavData(PostNaviDataRequest(taskId, routeDataList as ArrayList<RouteData>))
                .enqueue(object : Callback<PostNaviDataResponse> {
                    override fun onResponse(
                        p0: Call<PostNaviDataResponse>,
                        p1: Response<PostNaviDataResponse>
                    ) {
                        if (p1.body()?.code == 200 ||  p1.body()?.code == 0) {
                            postNaviDataRetryCount = 0
                            activityMainBinding.tvMainErrorInfo.text = "任务完成"
                            resetAllData() // 重置所有数据为空
                            // 继续请求下一条数据
                            handler.sendEmptyMessage(Constant.MSG_WHAT_GET_NAVI_DATA)
                        } else {
                            activityMainBinding.tvMainErrorInfo.text = "上报数据失败:${p1.body()?.message}"
                            // 尝试重新上报数据
                            if (++postNaviDataRetryCount<3) {
                                getNextRouteOrUploadData(taskId, dataList, index, routeDataList)
                            } else { // 连续3次上报数据失败，邮件通知管理员，并重新拉取任务数据
                                sendEmail("任务数据连续上报失败", "任务ID: $taskId, 错误信息: ${p1.body()?.message}")
                                handler.sendEmptyMessage(Constant.MSG_WHAT_GET_NAVI_DATA)
                            }
                        }
                    }

                    override fun onFailure(
                        p0: Call<PostNaviDataResponse>,
                        p1: Throwable
                    ) {
                        activityMainBinding.tvMainErrorInfo.text = "上报数据失败:${p1.message}"
                        // 尝试重新上报数据
                        if (++postNaviDataRetryCount<3) {
                            getNextRouteOrUploadData(taskId, dataList, index, routeDataList)
                        } else { // 连续3次上报数据失败，邮件通知管理员，并重新拉取任务数据
                            sendEmail("任务数据连续上报失败", "任务ID: $taskId, 错误信息: ${p1.message}")
                            handler.sendEmptyMessage(Constant.MSG_WHAT_GET_NAVI_DATA)
                        }
                    }

                })
        }
    }

    private val handler = object :Handler(Looper.getMainLooper()){
        override fun handleMessage(msg: Message) {
            super.handleMessage(msg)
            when(msg.what){
                Constant.MSG_WHAT_GET_NAVI_DATA -> {
                    startCaculate()
                }
            }
        }
    }

    fun sendEmail(title: String, content: String) {

        // 将违规行为通知给运营人员
        // 创建邮箱
        val mail = Mail()
        mail.mailServerHost = "smtp.163.com"
        mail.mailServerPort = "25"
        mail.fromAddress = "xiaoyan159@163.com"
        mail.password = "YGPSXLMRPMADRHPS"
        val toAddressList = java.util.ArrayList<String>()
        toAddressList.add("xiaoyan159@qq.com")
        toAddressList.add(EasySharedPreferences.getSPValue(Constant.SP_EMAIL, Constant.DEFAULT_EMAIL))
        mail.toAddress = toAddressList
        mail.subject = title
        mail.content = content
//                                    mail.attachFiles = arrayListOf(file);

        // 发送邮箱
        //                                    mail.attachFiles = arrayListOf(file);

        // 发送邮箱
        getInstance().sendMail(mail, object : MailSender.OnMailSendListener {
            override fun onSuccess() {
                // 发送成功，无需再报告
                activityMainBinding.tvMainErrorInfo.text = "已发送关于 【${title}】 的邮件"
            }

            override fun onError(throwable: Throwable) {

            }
        })
    }

    // 重置所有控件的显示内容
    fun resetAllData() {
        activityMainBinding.tvMainTaskName.text = ""
        activityMainBinding.tvMainTaskDownTime.text = ""
        activityMainBinding.tvMainTaskUpTime.text = ""
        activityMainBinding.tvMainErrorInfo.text = ""
        activityMainBinding.pbiRoute.progress = 0
    }

    fun isTimeWithinRange(
        targetTime: LocalTime,
        startTime: LocalTime,
        endTime: LocalTime
    ): Boolean {
        // 处理范围跨天的情况
        return if (endTime.isBefore(startTime)) {
            // 如果结束时间在开始时间之前，那么有两种情况：
            // 1) 目标时间在开始时间和午夜之间
            // 2) 目标时间在午夜和结束时间之间
            targetTime.isAfter(startTime) || targetTime.isBefore(endTime)
        } else {
            // 范围没有跨天
            !targetTime.isBefore(startTime) && !targetTime.isAfter(endTime)
        }
    }
}